package com.nononsenseapps.feeder.db.entity

import androidx.room.*
import com.nononsenseapps.feeder.db.*
import com.nononsenseapps.feeder.db.room.ID_UNSET
import com.nononsenseapps.feeder.util.relativeLinkIntoAbsolute
import com.nononsenseapps.feeder.util.sloppyLinkToStrictURL
import com.nononsenseapps.jsonfeed.Attachment
import com.nononsenseapps.jsonfeed.Author
import com.nononsenseapps.jsonfeed.Item
import org.joda.time.DateTime
import org.joda.time.DateTimeZone
import timber.log.Timber
import java.net.URI
import java.net.URL

const val ITEM_BODY_FORMAT_TYPE_NO_SET=0
const val ITEM_BODY_FORMAT_TYPE_HTML=1
const val ITEM_BODY_FORMAT_TYPE_MARKDOWN=2

@Entity(tableName = FEED_ITEM.tableName,
        indices = [Index(value = [FEED_ITEM.COL_GUID, FEED_ITEM.COL_FEED_ID], unique = true),
            Index(value = [FEED_ITEM.COL_FEED_ID]),Index(value = [FEED_ITEM.COL_ITEM_FEATURE])],
        foreignKeys = [ForeignKey(entity = Feed::class,
                parentColumns = [FEED.COL_ID],
                childColumns = [FEED_ITEM.COL_FEED_ID],
                onDelete = ForeignKey.CASCADE),
              ForeignKey(entity = FeedItemFeature::class,
                    parentColumns = [FEED_ITEMS_FEATURE.COL_ID],
                    childColumns = [FEED_ITEM.COL_ITEM_FEATURE],
                    onDelete = ForeignKey.SET_NULL)
        ])
data class FeedItem @Ignore constructor(
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = FEED_ITEM.COL_ID) var id: Long = ID_UNSET,
    @ColumnInfo(name = FEED_ITEM.COL_GUID) var guid: String = "",
    @ColumnInfo(name = FEED_ITEM.COL_TITLE) var title: String = "",
    @ColumnInfo(name = FEED_ITEM.COL_DESCRIPTION) var description: String = "",
    @ColumnInfo(name = FEED_ITEM.COL_PLAIN_TITLE) var plainTitle: String = "",
    @ColumnInfo(name = FEED_ITEM.COL_PLAIN_SNIPPET) var plainSnippet: String = "",
    @ColumnInfo(name = FEED_ITEM.COL_IMAGE_URL) var imageUrl: String? = null,
    @ColumnInfo(name = FEED_ITEM.COL_ENCLOSURE_LINK) var enclosureLink: String? = null,
    @ColumnInfo(name = FEED_ITEM.COL_AUTHOR) var author: String? = null,
    @ColumnInfo(name = FEED_ITEM.COL_PUB_DATE, typeAffinity = ColumnInfo.TEXT) var pubDate: DateTime? = null,
    @ColumnInfo(name = FEED_ITEM.COL_LINK) var link: String? = null,
    @ColumnInfo(name = FEED_ITEM.COL_UNREAD) var unread: Boolean = true,
    @ColumnInfo(name = FEED_ITEM.COL_NOTIFIED) var notified: Boolean = false,
    @ColumnInfo(name = FEED_ITEM.COL_FEED_ID) var feedId: Long? = null,
    @ColumnInfo(name = FEED_ITEM.COL_IMAGE_COUNT) var image_count: Int = 0,
    @ColumnInfo(name = FEED_ITEM.COL_CREATE_DATE, typeAffinity = ColumnInfo.INTEGER) var createDate: DateTime = DateTime.now(DateTimeZone.UTC),
    @ColumnInfo(name = FEED_ITEM.COL_ITEM_TAGS) var itemTags: String = "",
    @ColumnInfo(name = FEED_ITEM.COL_READ_HISTORY, typeAffinity = ColumnInfo.TEXT) var readHistory: DateTime? = null,
    @ColumnInfo(name = FEED_ITEM.COL_ITEM_FEATURE)  var feature: Long? = null,
    @ColumnInfo(name = FEED_ITEM.COL_RULE_CHECKED) var ruleChecked: Boolean = false,
    @ColumnInfo(name = FEED_ITEM.COL_ATTENTION_LEVEL) var attentionLevel: Int = ATTENTION_NORMAL,
    @ColumnInfo(name = FEED_ITEM.COL_WORD_COUNT) var wordCount: Int = 0,
    @ColumnInfo(name = FEED_ITEM.COL_FULL_TEXT_SYNC, defaultValue = "0") var fullTextSync: Boolean = false,
    @ColumnInfo(name = FEED_ITEM.COL_BODY_FORMAT_TYPE, defaultValue = ITEM_BODY_FORMAT_TYPE_NO_SET.toString()) var bodyFormatType: Int = ITEM_BODY_FORMAT_TYPE_NO_SET
) {

    constructor() : this(id = ID_UNSET)

    fun updateFromParsedEntry(entry: Item, feed: com.nononsenseapps.jsonfeed.Feed) {
        //Timber.d("updateFromParsedEntry entry.:$entry")
        // Be careful about nulls.
        val text = entry.content_html ?: entry.content_text ?: this.description
        this.wordCount= text.length
        //Timber.d("text:${text}\n contentText:${contentText} \n wordCount:$wordCount")
        val summary: String? = entry.summary ?: entry.content_text //?: htmlToPlainConverter().convert(text).take(100) //htmlRegex.replace(if(text.length>500) text.take(500)+">" else text,"")

        val absoluteImage = when {
            feed.feed_url != null && entry.image != null -> relativeLinkIntoAbsolute(sloppyLinkToStrictURL(feed.feed_url!!), entry.image!!)
            else -> entry.image
        }

        entry.id?.let { this.guid = it }
        entry.title?.let { this.title = it }
        text.let { this.description = it }
        //entry.title?.let { this.plainTitle = htmlToPlainConverter().convert(it) }
        entry.title?.let { this.plainTitle = it }
        summary?.let { this.plainSnippet = it }

        this.imageUrl = absoluteImage
        this.enclosureLink = entry.attachments?.firstOrNull()?.url
        this.author = entry.author?.name ?: feed.author?.name
        this.link = entry.url
        entry.imageCount?.let {this.image_count=it}

        this.pubDate =DateTime.now(DateTimeZone.UTC)
        entry.date_published?.let{
            try {
                // Allow an actual pubdate to be updated
                pubDate= DateTime.parse(it)
            } catch (t: Throwable) {
                Timber.d(t)
            }
        }

        this.createDate = DateTime.now(DateTimeZone.UTC)
        entry.date_modified?.let {
            try {
                // Allow an actual pubdate to be updated
                createDate= DateTime.parse(it)
            } catch (t: Throwable) {
                Timber.d(t)
            }
        }

        //bug check: entry.tags => [null] not null
        if(!entry.tags.isNullOrEmpty()){
            entry.tags!!.joinToString().let { this.itemTags = it }
        }

    }

    fun convertToJsonFeedItem():Item=Item(
            id=this.guid,
            title = this.title,
            summary = this.plainSnippet,
            content_html = this.description,
            url=link,
            date_published = this.pubDateString,
            attachments = this.enclosureLink?.let{ listOf(Attachment(it))},
            author = this.author?.let { Author(it) },
            image = this.imageUrl
    )


    val pubDateString: String?
        get() = pubDate?.toString()

    val enclosureFilename: String?
        get() {
            if (enclosureLink != null) {
                var fname: String? = null
                try {
                    fname = URI(enclosureLink).path.split("/").last()
                } catch (e: Exception) {
                }
                return if (fname == null || fname.isEmpty()) {
                    null
                } else {
                    fname
                }
            }
            return null
        }

    val domain: String?
        get() {
            val l: String? = enclosureLink ?: link
            if (l != null) {
                try {
                    return URL(l).host.replace("www.", "")
                } catch (e: Throwable) {
                }
            }
            return null
        }

    fun tags():List<String>{
        return itemTags.split(",")
    }
}

